home *** CD-ROM | disk | FTP | other *** search
- """HTTP client class
-
- See the following URL for a description of the HTTP/1.0 protocol:
- http://www.w3.org/hypertext/WWW/Protocols/
- (I actually implemented it from a much earlier draft.)
-
- Example:
-
- >>> from httplib import HTTP
- >>> h = HTTP('www.python.org')
- >>> h.putrequest('GET', '/index.html')
- >>> h.putheader('Accept', 'text/html')
- >>> h.putheader('Accept', 'text/plain')
- >>> h.endheaders()
- >>> errcode, errmsg, headers = h.getreply()
- >>> if errcode == 200:
- ... f = h.getfile()
- ... print f.read() # Print the raw HTML
- ...
- <HEAD>
- <TITLE>Python Language Home Page</TITLE>
- [...many more lines...]
- >>>
-
- Note that an HTTP object is used for a single request -- to issue a
- second request to the same server, you create a new HTTP object.
- (This is in accordance with the protocol, which uses a new TCP
- connection for each request.)
- """
-
- import os
- import socket
- import string
- import mimetools
-
- try:
- from cStringIO import StringIO
- except:
- from StringIO import StringIO
-
- HTTP_VERSION = 'HTTP/1.0'
- HTTP_PORT = 80
- HTTPS_PORT = 443
-
- class FakeSocket:
- def __init__(self, sock, ssl):
- self.__sock = sock
- self.__ssl = ssl
- return
-
- def makefile(self, mode): # hopefully, never have to write
- msgbuf = ""
- while 1:
- try:
- msgbuf = msgbuf + self.__ssl.read()
- except socket.sslerror, msg:
- break
- return StringIO(msgbuf)
-
- def send(self, stuff, flags = 0):
- return self.__ssl.write(stuff)
-
- def recv(self, len = 1024, flags = 0):
- return self.__ssl.read(len)
-
- def __getattr__(self, attr):
- return getattr(self.__sock, attr)
-
- class HTTP:
- """This class manages a connection to an HTTP server."""
-
- def __init__(self, host = '', port = 0, **x509):
- """Initialize a new instance.
-
- If specified, `host' is the name of the remote host to which
- to connect. If specified, `port' specifies the port to which
- to connect. By default, httplib.HTTP_PORT is used.
-
- """
- self.key_file = x509.get('key_file')
- self.cert_file = x509.get('cert_file')
- self.debuglevel = 0
- self.file = None
- if host: self.connect(host, port)
-
- def set_debuglevel(self, debuglevel):
- """Set the debug output level.
-
- A non-false value results in debug messages for connection and
- for all messages sent to and received from the server.
-
- """
- self.debuglevel = debuglevel
-
- def connect(self, host, port = 0):
- """Connect to a host on a given port.
-
- Note: This method is automatically invoked by __init__,
- if a host is specified during instantiation.
-
- """
- if not port:
- i = string.find(host, ':')
- if i >= 0:
- host, port = host[:i], host[i+1:]
- try: port = string.atoi(port)
- except string.atoi_error:
- raise socket.error, "nonnumeric port"
- if not port: port = HTTP_PORT
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- if self.debuglevel > 0: print 'connect:', (host, port)
- self.sock.connect((host, port))
-
- def send(self, str):
- """Send `str' to the server."""
- if self.debuglevel > 0: print 'send:', `str`
- self.sock.send(str)
-
- def putrequest(self, request, selector):
- """Send a request to the server.
-
- `request' specifies an HTTP request method, e.g. 'GET'.
- `selector' specifies the object being requested, e.g.
- '/index.html'.
-
- """
- if not selector: selector = '/'
- str = '%s %s %s\r\n' % (request, selector, HTTP_VERSION)
- self.send(str)
-
- def putheader(self, header, *args):
- """Send a request header line to the server.
-
- For example: h.putheader('Accept', 'text/html')
-
- """
- str = '%s: %s\r\n' % (header, string.joinfields(args,'\r\n\t'))
- self.send(str)
-
- def endheaders(self):
- """Indicate that the last header line has been sent to the server."""
- self.send('\r\n')
-
- def getreply(self):
- """Get a reply from the server.
-
- Returns a tuple consisting of:
- - server response code (e.g. '200' if all goes well)
- - server response string corresponding to response code
- - any RFC822 headers in the response from the server
-
- """
- self.file = self.sock.makefile('rb')
- line = self.file.readline()
- if self.debuglevel > 0: print 'reply:', `line`
- try:
- [ver, code, msg] = string.split(line, None, 2)
- except ValueError:
- try:
- [ver, code] = string.split(line, None, 1)
- msg = ""
- except ValueError:
- self.headers = None
- return -1, line, self.headers
- if ver[:5] != 'HTTP/':
- self.headers = None
- return -1, line, self.headers
- errcode = string.atoi(code)
- errmsg = string.strip(msg)
- self.headers = mimetools.Message(self.file, 0)
- return errcode, errmsg, self.headers
-
- def getfile(self):
- """Get a file object from which to receive data from the HTTP server.
-
- NOTE: This method must not be invoked until getreplies
- has been invoked.
-
- """
- return self.file
-
- def close(self):
- """Close the connection to the HTTP server."""
- if self.file:
- self.file.close()
- self.file = None
- if self.sock:
- self.sock.close()
- self.sock = None
-
- if hasattr(socket, "ssl"):
- class HTTPS(HTTP):
- """This class allows communication via SSL."""
-
- def connect(self, host, port = 0):
- """Connect to a host on a given port.
-
- Note: This method is automatically invoked by __init__,
- if a host is specified during instantiation.
-
- """
- if not port:
- i = string.find(host, ':')
- if i >= 0:
- host, port = host[:i], host[i+1:]
- try: port = string.atoi(port)
- except string.atoi_error:
- raise socket.error, "nonnumeric port"
- if not port: port = HTTPS_PORT
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- if self.debuglevel > 0: print 'connect:', (host, port)
- sock.connect((host, port))
- ssl = socket.ssl(sock, self.key_file, self.cert_file)
- self.sock = FakeSocket(sock, ssl)
-
-
- def test():
- """Test this module.
-
- The test consists of retrieving and displaying the Python
- home page, along with the error code and error string returned
- by the www.python.org server.
-
- """
- import sys
- import getopt
- opts, args = getopt.getopt(sys.argv[1:], 'd')
- dl = 0
- for o, a in opts:
- if o == '-d': dl = dl + 1
- print "testing HTTP..."
- host = 'www.python.org'
- selector = '/'
- if args[0:]: host = args[0]
- if args[1:]: selector = args[1]
- h = HTTP()
- h.set_debuglevel(dl)
- h.connect(host)
- h.putrequest('GET', selector)
- h.endheaders()
- errcode, errmsg, headers = h.getreply()
- print 'errcode =', errcode
- print 'errmsg =', errmsg
- print
- if headers:
- for header in headers.headers: print string.strip(header)
- print
- print h.getfile().read()
- if hasattr(socket, "ssl"):
- print "-"*40
- print "testing HTTPS..."
- host = 'synergy.as.cmu.edu'
- selector = '/~geek/'
- if args[0:]: host = args[0]
- if args[1:]: selector = args[1]
- h = HTTPS()
- h.set_debuglevel(dl)
- h.connect(host)
- h.putrequest('GET', selector)
- h.endheaders()
- errcode, errmsg, headers = h.getreply()
- print 'errcode =', errcode
- print 'errmsg =', errmsg
- print
- if headers:
- for header in headers.headers: print string.strip(header)
- print
- print h.getfile().read()
-
-
- if __name__ == '__main__':
- test()
-